package com.dabai.applicationmanager.ui.smallprogram;

import android.Manifest;
import android.annotation.SuppressLint;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.ClipData;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Log;
import android.view.ActionMode;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.CheckBox;
import android.widget.LinearLayout;

import androidx.core.app.NotificationCompat;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;

import com.chad.library.adapter.base.BaseQuickAdapter;
import com.dabai.applicationmanager.R;
import com.dabai.applicationmanager.adapter.AppScanAdapter;
import com.dabai.applicationmanager.bean.AppScanBaseInfo;
import com.dabai.applicationmanager.databinding.ActivityScanInstallationPackageBinding;
import com.dabai.applicationmanager.dialog.MdcDialog;
import com.dabai.applicationmanager.dialog.TipAlertDialog;
import com.dabai.applicationmanager.impl.OnCompleteListener;
import com.dabai.applicationmanager.sort.ComparatorByLastModified;
import com.dabai.applicationmanager.utils.OtherUtils;
import com.dabai.dbutils.manager.CacheDataManager;
import com.dabai.dbutils.toast.DBToast;
import com.dabai.dbutils.utils.AppUtils;
import com.dabai.dbutils.utils.FileUtils;
import com.dabai.dbutils.utils.ShareUtils;
import com.dabai.dbutils.utils.SharedPreferencesUtils;
import com.dabai.dbutils.utils.UriUtils;
import com.dabai.uitools.base.BaseAppCompatActivity;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.permissionx.guolindev.PermissionX;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Timer;
import java.util.TimerTask;

import me.zhanghai.android.fastscroll.FastScrollerBuilder;

public class ScanInstallationPackageActivity extends BaseAppCompatActivity {


    ActivityScanInstallationPackageBinding asi;
    Context context;

    private AppScanAdapter appScanAdapter;
    private ArrayList<AppScanBaseInfo> appScanBaseInfo;
    private List<PackageInfo> packageInfo;
    private ArrayList<AppScanBaseInfo> appBaseInflows;


    NotificationManager notificationManager;
    private NotificationCompat.Builder notification;
    private ArrayList<String> delList;


    private ArrayList<File> scanFiles = new ArrayList<>();

    /*扫描线程*/
    private Thread scanThread;
    /*定时器  用于定时检测扫描线程的状态*/
    private Timer scanTimer;

    /*检测扫描线程的任务*/
    private TimerTask scanTask;
    private PackageManager pm;
    private List<File> fileArray;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        asi = ActivityScanInstallationPackageBinding.inflate(getLayoutInflater());
        setContentView(asi.getRoot());
        context = this;

        Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true);


        PermissionX.init(this)
                .permissions(Manifest.permission.WRITE_EXTERNAL_STORAGE)
                .request((allGranted, grantedList, deniedList) -> {
                    if (!allGranted) {
                        DBToast.showText(context, "无储存权限，不能扫描外部目录。", false);
                        finish();
                    }
                });

        TipAlertDialog.init(context);

        asi.recyclerView.setLayoutManager(new LinearLayoutManager(this));
        asi.recyclerView.addItemDecoration(new DividerItemDecoration(this, LinearLayout.VERTICAL));

        new FastScrollerBuilder(asi.recyclerView).build();


        new MaterialAlertDialogBuilder(context)
                .setTitle("扫描方式")
                .setNeutralButton("取消", (dialog, which) -> finish())
                .setItems(new String[]{"全盘扫描", "扫描下载文件夹", "查询系统媒体库"}, (dialog, which) -> {
                    if (which == 0) {
                        startScan(Environment.getExternalStorageDirectory().getAbsolutePath());
                    }
                    if (which == 1) {
                        startScan(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath());
                    }
                    if (which == 2) {
                        queryFiles();
                    }
                }).show().getWindow().setWindowAnimations(com.dabai.uitools.R.style.DBAnim_Transitions_Via);


        initNotification();

    }

    /**
     * init通知
     */
    public void initNotification() {

        notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);


        notification = new NotificationCompat.Builder(context, "extract_progress")
                .setSmallIcon(R.drawable.ic_round_android_24)
                .setContentTitle("操作进度")
                .setContentText("正在执行")
                .setProgress(100, 0, false);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            //通知 强度
            int importance = NotificationManager.IMPORTANCE_NONE;
            NotificationChannel channel = new NotificationChannel("extract_progress", "执行进度", importance);
            notificationManager.createNotificationChannel(channel);
        }

    }


    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int itemId = item.getItemId();
        if (itemId == android.R.id.home) {
            finish();
            return true;
        }
        if (itemId == R.id.choose) {

            //通过系统的文件浏览器选择一个文件
            Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
            //筛选，只显示可以“打开”的结果，如文件(而不是联系人或时区列表)
            intent.addCategory(Intent.CATEGORY_OPENABLE);
            //过滤只显示图像类型文件
            intent.setType("*/*");

            if (OtherUtils.getImplementWay(context) != 1) {
                intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
            }

            startActivityForResult(intent, 301);

            return true;
        }
        if (itemId == R.id.clean) {

            if (delList.size() <= 0) {
                DBToast.showYellowToast(context, "没有需要清理的软件包!");
                return true;
            }

            MdcDialog.showConfirmDialog(context, "提示", "是否要删除已经安装的 " + delList.size() + " 个软件包?", new MdcDialog.OnConfirmDialogButtonListener() {
                @Override
                public void confirm() {

                    for (String path : delList) {
                        FileUtils.delete(path);
                    }
                    DBToast.showText(context, "删除完成!", true);

                }

                @Override
                public void cancel() {

                }
            }).getWindow().setWindowAnimations(com.dabai.uitools.R.style.DBAnim_Transitions_Via);
            return true;
        }
        return super.onOptionsItemSelected(item);
    }


    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode == 301 && resultCode == RESULT_OK) {

            appBaseInflows = new ArrayList<>();

            if (data.getData() != null) {
                //单次点击未使用多选的情况
                UriUtils uriUtils = new UriUtils(context, data.getData());
                File tagFile = new File(OtherUtils.getTmpDirectory(context), uriUtils.getFileName());
                boolean isOk = uriUtils.copyFile(tagFile);
                if (isOk) {
                    appBaseInflows.add(new AppScanBaseInfo(
                            ""
                            , tagFile.getAbsolutePath()
                            , null, tagFile.getName(), "", ""));
                }
                setProgress(0);

                OtherUtils.installApks(ScanInstallationPackageActivity.this
                        , appBaseInflows, new OnCompleteListener() {
                            @Override
                            public void start() {
                            }

                            @Override
                            public void complete() {
                                setProgressComplete("全部安装完成!");
                            }

                            @Override
                            public void progress(int progress) {
                                setNotProgress(progress);
                            }
                        });

            } else {
                //长按使用多选的情况
                ClipData clipData = data.getClipData();
                if (clipData != null) {

                    TipAlertDialog.getInstance(context).showTipLayout("正在准备文件...");
                    setProgress(0);

                    new Thread(() -> {

                        for (int i = 0; i < clipData.getItemCount(); i++) {
                            ClipData.Item item = clipData.getItemAt(i);

                            Uri uri = item.getUri();

                            UriUtils uriUtils = new UriUtils(context, uri);

                            File tagFile = new File(OtherUtils.getTmpDirectory(context), uriUtils.getFileName());
                            boolean isOk;
                            if (tagFile.exists()) {
                                isOk = true;
                            } else {
                                isOk = uriUtils.copyFile(tagFile);
                            }
                            if (isOk) {
                                appBaseInflows.add(new AppScanBaseInfo(
                                        ""
                                        , tagFile.getAbsolutePath()
                                        , null, tagFile.getName(), "", ""));
                            }
                        }
                        runOnUiThread(() -> {
                            TipAlertDialog.getInstance(context).hideTipLayout();
                            OtherUtils.installApks(ScanInstallationPackageActivity.this
                                    , appBaseInflows, new OnCompleteListener() {
                                        @Override
                                        public void start() {
                                        }

                                        @Override
                                        public void complete() {
                                            setProgressComplete("全部安装完成!");
                                            CacheDataManager.clearAllCache(context);
                                        }

                                        @Override
                                        public void progress(int progress) {
                                            setNotProgress(progress);
                                        }
                                    });
                        });
                    }).start();

                }
            }

        }
    }


    /**
     * 查询文件
     * 查询SD卡里安装包
     */
    private void queryFiles() {

        TipAlertDialog.getInstance(context).showTipLayout("正在查询系统媒体库...");

        new Thread(() -> {


            appScanBaseInfo = new ArrayList<>();
            delList = new ArrayList<>();
            List<File> fileArray = new ArrayList<>();

            // AppIconLoader appIconLoader = new AppIconLoader(130, true, context);
            PackageManager pm = context.getPackageManager();

            String[] projection = new String[]{MediaStore.Files.FileColumns._ID,
                    MediaStore.Files.FileColumns.DATA,
                    MediaStore.Files.FileColumns.SIZE
            };
            Cursor cursor = getContentResolver().query(
                    Uri.parse("content://media/external/file"),
                    projection,
                    MediaStore.Files.FileColumns.DATA + " like ?",
                    new String[]{"%.apk"},
                    null);

            if (cursor != null) {
                if (cursor.moveToFirst()) {

                    int dataindex = cursor
                            .getColumnIndex(MediaStore.Files.FileColumns.DATA);

                    do {
                        String path = cursor.getString(dataindex);

                        PackageInfo info = pm.getPackageArchiveInfo(path, 0);

                        if (info != null) {

                            //如果 minAPI比本机大  则不显示
                            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                                if (Build.VERSION.SDK_INT < info.applicationInfo.minSdkVersion) {
                                    continue;
                                }
                            }

                            //添加到列表
                            fileArray.add(new File(path));
                            //已经安装的列表
                            if (AppUtils.isInstalled(context, info.packageName)) {
                                delList.add(path);
                            }
                        }

                    } while (cursor.moveToNext());

                }
            }
            if (cursor != null) {
                cursor.close();
            }

            Collections.sort(fileArray, new ComparatorByLastModified(false));

            for (File file : fileArray) {
                String path = file.getAbsolutePath();
                PackageInfo info = pm.getPackageArchiveInfo(path, 0);

                appScanBaseInfo.add(new AppScanBaseInfo(
                        AppUtils.isInstalled(context, info.packageName) ? "" : "未安装"
                        , path
                        , getApkIcon(context, path)
                        , new File(path).getName()
                        , info.packageName, info.versionName + "(" + info.versionCode + ")"));

            }

            //使用数据
            appScanAdapter = new AppScanAdapter(appScanBaseInfo, context);
            appScanAdapter.setAnimationWithDefault(BaseQuickAdapter.AnimationType.AlphaIn);


            addAdapterEvents(appScanAdapter);

        }).start();

    }


    private void addAdapterEvents(AppScanAdapter appScanAdapter) {
        appScanAdapter.setOnItemClickListener((adapter, view, position) -> {

            //多选模式 , 拦截 之前的单击事件
            if (appScanAdapter.isSelect()) {
                CheckBox checkBox = (CheckBox) adapter.getViewByPosition(position, R.id.checkBox);

                if (checkBox != null) {
                    if (!checkBox.isChecked()) {
                        checkBox.setChecked(true);
                        appScanAdapter.setCheckData(position, true);

                    } else {
                        checkBox.setChecked(false);
                        appScanAdapter.setCheckData(position, false);
                    }
                    actionMode.setTitle("已经选择" + appScanAdapter.getCheckData().size() + "项");
                }

                return;
            }

            //之前的单击事件
            AppScanBaseInfo appScanBaseInfo = (AppScanBaseInfo) adapter.getData().get(position);

            appBaseInflows = new ArrayList<>();
            appBaseInflows.add(appScanBaseInfo);

            OtherUtils.installApks(ScanInstallationPackageActivity.this, appBaseInflows, new OnCompleteListener() {
                @Override
                public void start() {
                }

                @Override
                public void complete() {
                }

                @Override
                public void progress(int progress) {
                }
            });

        });

        runOnUiThread(() -> {
            asi.recyclerView.setAdapter(appScanAdapter);
            TipAlertDialog.getInstance(context).hideTipLayout();
            setTitle("扫描软件包(" + appScanAdapter.getData().size() + ")");
        });


        appScanAdapter.setOnItemLongClickListener((adapter, view, position) -> {

            //长按进去 多选模式
            if (!appScanAdapter.isSelect()) {
                if (actionMode == null) {
                    actionMode = startActionMode(actionCallback);
                }
                appScanAdapter.setSelect(true);
                appScanAdapter.showAllCheckBox();

                appScanAdapter.setCheckView(position, true);
                appScanAdapter.setCheckData(position, true);

                actionMode.setTitle("已经选择" + appScanAdapter.getCheckData().size() + "项");

            }

            return true;
        });
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {

        getMenuInflater().inflate(R.menu.sipa, menu);

        return super.onCreateOptionsMenu(menu);
    }


    public void setNotProgress(int pro) {
        if (
                SharedPreferencesUtils.getDefaultSharedPreferences(context)
                        .getBoolean("notificationBarSchedule", true)) {
            if (notification != null) {
                // 设置新的百分比
                notification.setContentText(pro + "%").
                        setProgress(100, pro, false);
                // 发送通知
                notificationManager.notify(100, notification.build());
            }
        }
    }

    public void setProgressComplete(String content) {
        if (
                SharedPreferencesUtils.getDefaultSharedPreferences(context)
                        .getBoolean("notificationBarSchedule", true)) {
            if (notification != null) {

                notification.setContentText(content)
                        .setProgress(0, 0, false);
                notificationManager.notify(100, notification.build());
            }
        }
    }

    public void setProgressContent(String content) {
        if (
                SharedPreferencesUtils.getDefaultSharedPreferences(context)
                        .getBoolean("notificationBarSchedule", true)) {
            if (notification != null) {
                notification.setContentText(content);
                notificationManager.notify(100, notification.build());
            }
        }
    }


    /**
     * ActionMode 回调
     */
    private ActionMode actionMode;
    private ActionMode.Callback actionCallback = new ActionMode.Callback() {

        @Override
        public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
            mode.setTitle("多选模式");
            return false;
        }

        @Override
        public void onDestroyActionMode(ActionMode mode) {
            //销毁时清空 所有数据
            appScanAdapter.setSelect(false);
            actionMode = null;
            appScanAdapter.hideAllCheckBox();

        }

        // 从XML菜单中加载菜单
        @Override
        public boolean onCreateActionMode(ActionMode mode, Menu menu) {
            MenuInflater inflater = getMenuInflater();

            if (OtherUtils.getImplementWay(context) == 1) {
                inflater.inflate(R.menu.action_app_scan_normal, menu);
            } else {
                inflater.inflate(R.menu.action_app_scan, menu);
            }
            return true;
        }


        // 菜单被点击
        @SuppressLint("NonConstantResourceId")
        @Override
        public boolean onActionItemClicked(ActionMode mode, MenuItem item) {

            appBaseInflows = appScanAdapter.getCheckAppInflows();

            switch (item.getItemId()) {
                case R.id.selectAll:
                    appScanAdapter.selectAllCheckBox();
                    actionMode.setTitle("已经选择" + appScanAdapter.getCheckData().size() + "项");
                    break;
                case R.id.cancelAll:
                    appScanAdapter.cancelSelectAllCheckBox();
                    actionMode.setTitle("已经选择" + appScanAdapter.getCheckData().size() + "项");
                    break;
                case R.id.inverseSelect:
                    appScanAdapter.inverseSelectAllCheckBox();
                    actionMode.setTitle("已经选择" + appScanAdapter.getCheckData().size() + "项");
                    break;
                case R.id.install:

                    if (appScanAdapter.getCheckDataSize() <= 0) {
                        DBToast.showYellowToast(context, "未选中任何列表项!");
                        return true;
                    }

                    OtherUtils.installApks(ScanInstallationPackageActivity.this, appBaseInflows, new OnCompleteListener() {
                        @Override
                        public void start() {
                            actionMode.finish();
                        }

                        @Override
                        public void complete() {
                            setProgressComplete("全部安装完成!");
                        }

                        @Override
                        public void progress(int progress) {
                            setNotProgress(progress);
                        }
                    });

                    break;
                case R.id.send:

                    if (appScanAdapter.getCheckDataSize() <= 0) {
                        DBToast.showYellowToast(context, "未选中任何列表项!");
                        return true;
                    }

                    MdcDialog.showConfirmDialog(context,
                            "提示", "确定发送选中的 " + appBaseInflows.size() + " 个安装包嘛? 总体积约为 " + FileUtils.formatFileSizeToString(appScanAdapter.getCheckAppSize())
                            , new MdcDialog.OnConfirmDialogButtonListener() {
                                @Override
                                public void confirm() {
                                    actionMode.finish();
                                    ArrayList<File> shareList = new ArrayList<>();

                                    new Thread(() -> {

                                        for (AppScanBaseInfo appScanBaseInfo : appBaseInflows) {
                                            File soc = new File(appScanBaseInfo.getPath());
                                            if (soc.exists()) {
                                                shareList.add(soc);
                                            }
                                        }

                                        ShareUtils.shareMultipleFile(context, "*/*", shareList);

                                    }).start();

                                }

                                @Override
                                public void cancel() {

                                }
                            }).getWindow().setWindowAnimations(com.dabai.uitools.R.style.DBAnim_Transitions_Via);


                    break;
                case R.id.delete:

                    if (appScanAdapter.getCheckDataSize() <= 0) {
                        DBToast.showYellowToast(context, "未选中任何列表项!");
                        return true;
                    }

                    MdcDialog.showConfirmDialog(context,
                            "提示", "确定删除选中的 " + appBaseInflows.size() + " 个安装包嘛? 删除完成后,释放储存空间约 " + FileUtils.formatFileSizeToString(appScanAdapter.getCheckAppSize())
                            , new MdcDialog.OnConfirmDialogButtonListener() {
                                @Override
                                public void confirm() {
                                    actionMode.finish();
                                    new Thread(() -> {

                                        for (AppScanBaseInfo appScanBaseInfo : appBaseInflows) {
                                            FileUtils.delete(appScanBaseInfo.getPath());
                                        }
                                        runOnUiThread(() -> {
                                            DBToast.showText(context, "全部删除完成!", true);
                                            finish();
                                        });
                                    }).start();

                                }

                                @Override
                                public void cancel() {

                                }
                            }).getWindow().setWindowAnimations(com.dabai.uitools.R.style.DBAnim_Transitions_Via);

                    break;
                default:
                    break;
            }
            return true;
        }

    };

    public static Drawable getApkIcon(Context context, String apkPath) {
        PackageManager pm = context.getPackageManager();
        PackageInfo info = pm.getPackageArchiveInfo(apkPath,
                PackageManager.GET_ACTIVITIES);
        if (info != null) {
            ApplicationInfo appInfo = info.applicationInfo;
            appInfo.sourceDir = apkPath;
            appInfo.publicSourceDir = apkPath;
            try {
                return appInfo.loadIcon(pm);
            } catch (OutOfMemoryError e) {
                Log.e("ApkIconLoader", e.toString());
            }
        }
        return null;
    }


    /*开始扫描*/
    private void startScan(String rootPath) {

        TipAlertDialog.getInstance(context).showTipLayout("正在全盘扫描安装包...");

        pm = context.getPackageManager();
        //使用数据

        delList = new ArrayList<>();
        fileArray = new ArrayList<>();

        appScanAdapter = new AppScanAdapter(appScanBaseInfo, context);
        appScanAdapter.setAnimationWithDefault(BaseQuickAdapter.AnimationType.AlphaIn);

        /*要扫描的文件后缀名*/
        final String endFilter = ".apk";

        final File dir = new File(rootPath);

        scanThread = new Thread(() -> scanFile(dir, endFilter));

        /*判断扫描是否完成 其实就是个定时任务 时间可以自己设置  每2s获取一下扫描线程的状态  如果线程状态为结束就说明扫描完成*/
        scanTimer = new Timer();
        scanTask = new TimerTask() {
            @Override
            public void run() {
                Log.i("线程状态", scanThread.getState().toString());

                if (scanThread.getState() == Thread.State.TERMINATED) {

                    Log.d("DBTAG", "fileArray: " + fileArray.size());

                    Collections.sort(fileArray, new ComparatorByLastModified(false));

                    appScanBaseInfo = new ArrayList<>();

                    for (File file1 : fileArray) {
                        String path1 = file1.getAbsolutePath();
                        PackageInfo info1 = pm.getPackageArchiveInfo(path1, 0);

                        appScanBaseInfo.add(new AppScanBaseInfo(
                                AppUtils.isInstalled(context, info1.packageName) ? "" : "未安装"
                                , path1
                                , getApkIcon(context, path1)
                                , new File(path1).getName()
                                , info1.packageName, info1.versionName + "(" + info1.versionCode + ")"));

                    }

                    //使用数据
                    appScanAdapter = new AppScanAdapter(appScanBaseInfo, context);
                    appScanAdapter.setAnimationWithDefault(BaseQuickAdapter.AnimationType.AlphaIn);


                    /*说明扫描线程结束 扫描完成  更新ui*/
                    runOnUiThread(() -> {
                        cancelTask();

                        TipAlertDialog.getInstance(context).hideTipLayout();

                        addAdapterEvents(appScanAdapter);

                    });
                }
            }
        };

        scanTimer.schedule(scanTask, 0, 1000);

        /*开始扫描*/
        scanThread.start();

    }


    /*扫描*/
    private void scanFile(File dir, String endFilter) {

        File[] files = dir.listFiles();

        if (files != null && files.length > 0) {

            for (File file : files) {

                if (file.getName().toUpperCase().endsWith(endFilter.toUpperCase())) {
                    /*是符合后缀名的文件  添加到列表中*/
                    String path = file.getAbsolutePath();
                    Log.d("DBTAG", "path : " + path);

                    PackageInfo info = pm.getPackageArchiveInfo(path, 0);

                    if (info != null) {

                        //如果 minAPI比本机大  则不显示
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                            if (Build.VERSION.SDK_INT < info.applicationInfo.minSdkVersion) {
                                continue;
                            }
                        }

                        //添加到列表
                        fileArray.add(new File(path));
                        //已经安装的列表
                        if (AppUtils.isInstalled(context, info.packageName)) {
                            delList.add(path);
                        }

                    }


                }

                //过滤常见目录 /storage/emulated/0/sina
                //  /storage/emulated/0/qqmusic
                //       /storage/emulated/0/netease

                /*是目录*/
                if (file.isDirectory() && !file.isHidden()) {
                    /*递归扫描*/
                    scanFile(file, endFilter);
                }
            }

        }
    }


    private void cancelTask() {

        Log.i("cancelTask", "结束任务");
        if (scanTask != null) {
            scanTask.cancel();
        }

        if (scanTimer != null) {
            scanTimer.purge();
            scanTimer.cancel();
        }
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
        TipAlertDialog.destroyTipLayout();
        cancelTask();
    }
}